<?php
namespace soa\image;
/**
 * 图片大小修改类
 * Class imageResize
 * @package service\kdhelp
 */
class imageResize
{

	public $source = '';
	public $target = '';

	private $_im;
	private $_imginfo = array();
	private $_tmpfile = '';
	private $_imagefunc;

	public function __construct($source,$info = array())
	{
		return $this->loadSource($source,$info);
	}

	public function getImgInfo(){
		return $this->_imginfo;
	}

	/**
	 * 加载图片源
	 * @param $source
	 * @param array $info
	 * @return bool
	 * @throws \Exception
	 */
	public function loadSource($source, $info = array())
	{

		clearstatcache();
		if (!is_readable($source)) {
			throw new \Exception('Image source is not readable');
		}

		if (empty($info)) {

			$imginfo = getimagesize($source);
			if ($imginfo === false) {
				throw new \Exception('get image size failed');
			}

			$this->_imginfo['width'] = $imginfo[0];
			$this->_imginfo['height'] = $imginfo[1];
			$this->_imginfo['mime'] = $imginfo['mime'];
			$this->_imginfo['size'] = filesize($source);

		} else {
			$this->_imginfo = $info;
		}

		switch ($this->_imginfo['mime']) {
			case 'image/jpeg':
				$imagecreatefromfunc = 'imagecreatefromjpeg';
				$imagefunc = 'imagejpeg';
				break;
			case 'image/gif':
				$imagecreatefromfunc = 'imagecreatefromgif';
				$imagefunc = 'imagegif';
				break;
			case 'image/png':
				$imagecreatefromfunc = 'imagecreatefrompng';
				$imagefunc = 'imagepng';
				break;
		}

		if (!function_exists($imagefunc)) {
			throw new \Exception('unknow function :' . $imagefunc);
		}

		$im = @$imagecreatefromfunc($source);
		if (!$im) {
			if (!function_exists('imagecreatefromstring')) {
				throw new \Exception('unknow function : imagecreatefromstring');
			}

			$fp = fopen($source, 'rb');
			$contents = fread($fp, filesize($source));
			fclose($fp);
			$im = imagecreatefromstring($contents);
			if ($im == FALSE) {
				return false;
			}
		}

		if ($this->_imginfo['mime'] == 'image/gif') {
			$fp = @fopen($source, 'rb');
			$content = fread($fp, $this->_imginfo['size']);
			fclose($fp);
			$this->_imginfo['animated'] = strpos($content, 'NETSCAPE2.0') === FALSE ? 0 : 1;
		}

		$this->source = $source;
		$this->_im = $im;
		$this->_imagefunc = $imagefunc;

		return true;
	}

	/**
	 * 计算图片尺寸
	 * @param $thumbwidth
	 * @param $thumbheight
	 * @param $method
	 * @return array
	 */
	private function _resize_size($thumbwidth, $thumbheight, $method)
	{
		$x = $y = $w = $h = 0;
		if ($method > 0) {
			$imgratio = $this->_imginfo['width'] / $this->_imginfo['height'];
			$thumbratio = $thumbwidth / $thumbheight;
			if ($imgratio >= 1 && $imgratio >= $thumbratio || $imgratio < 1 && $imgratio > $thumbratio) {
				$h = $this->_imginfo['height'];
				$w = $h * $thumbratio;
				$x = ($this->_imginfo['width'] - $thumbratio * $this->_imginfo['height']) / 2;
			} elseif ($imgratio >= 1 && $imgratio <= $thumbratio || $imgratio < 1 && $imgratio <= $thumbratio) {
				$w = $this->_imginfo['width'];
				$h = $w / $thumbratio;
			}
		} else {
			$x_ratio = $thumbwidth / $this->_imginfo['width'];
			$y_ratio = $thumbheight / $this->_imginfo['height'];
			if (($x_ratio * $this->_imginfo['height']) < $thumbheight) {
				$h = ceil($x_ratio * $this->_imginfo['height']);
				$w = $thumbwidth;
			} else {
				$w = ceil($y_ratio * $this->_imginfo['width']);
				$h = $thumbheight;
			}
		}
		return array($x, $y, $w, $h);
	}

	/**
	 * 通过宽高调整图片体积
	 * @param $attach_photo
	 * @param $thumbwidth
	 * @param $thumbheight
	 * @return bool
	 */
	private function _resize_bywh($attach_photo, $thumbwidth, $thumbheight)
	{
		if ($this->_imginfo['width'] >= $thumbwidth || $this->_imginfo['height'] >= $thumbheight) {
			$thumb = array();
			list(, , $thumb['width'], $thumb['height']) = $this->_resize_size($thumbwidth, $thumbheight, 0);
			$cx = $this->_imginfo['width'];
			$cy = $this->_imginfo['height'];
			$thumb_photo = imagecreatetruecolor($thumb['width'], $thumb['height']);
			imagecopyresampled($thumb_photo, $attach_photo, 0, 0, 0, 0, $thumb['width'], $thumb['height'], $cx, $cy);

			return $thumb_photo;
		}

		return false;
	}

	/**
	 * 通过比例调整图片体积
	 * @param $attach_photo
	 * @param $thumbwidth
	 * @param $thumbheight
	 * @return mixed
	 */
	private function _resize_byratio($attach_photo, $thumbwidth, $thumbheight)
	{
		if (!($this->_imginfo['width'] <= $thumbwidth || $this->_imginfo['height'] <= $thumbheight)) {
			list($startx, $starty, $cutw, $cuth) = $this->_resize_size($thumbwidth, $thumbheight, 1);
			$dst_photo = imagecreatetruecolor($cutw, $cuth);
			imagecopymerge($dst_photo, $attach_photo, 0, 0, $startx, $starty, $cutw, $cuth, 100);
			$thumb_photo = imagecreatetruecolor($thumbwidth, $thumbheight);
			imagecopyresampled($thumb_photo, $dst_photo, 0, 0, 0, 0, $thumbwidth, $thumbheight, $cutw, $cuth);
		} else {
			$thumb_photo = imagecreatetruecolor($thumbwidth, $thumbheight);
			$bgcolor = imagecolorallocate($thumb_photo, 255, 255, 255);
			imagefill($thumb_photo, 0, 0, $bgcolor);
			$startx = ($thumbwidth - $this->_imginfo['width']) / 2;
			$starty = ($thumbheight - $this->_imginfo['height']) / 2;
			imagecopymerge($thumb_photo, $attach_photo, $startx, $starty, 0, 0, $this->_imginfo['width'], $this->_imginfo['height'], 100);
		}

		return $thumb_photo;
	}

	/**
	 *
	 * @param null $target
	 * @return bool
	 */
	public function setTarget($target = null)
	{

		if (!$this->source) {
			return false;
		}

		if (!$target) {
			$target = $this->source;
		}

		$targetpath = dirname($target);
		if (!is_dir($targetpath) || !is_writable($targetpath)) {
			return false;
		}

		$this->target = $target;
		return true;
	}

	/**
	 * 生成缩略图
	 * @param $thumbwidth
	 * @param $thumbheight
	 * @param string $thumbtype
	 * @return bool
	 * @throws \Exception
	 */
	public function thumb($thumbwidth, $thumbheight, $thumbtype = 'wh')
	{

		if (!$this->_im) {
			throw new \Exception('no image source found');
		}

		if ($this->_imginfo['animated']) {
			return false;
		}

		if (!$this->target && !$this->setTarget()) {
			throw new \Exception('no taget set');
		}

		$thumbwidth = intval($thumbwidth);
		$thumbheight = intval($thumbheight);

		if (!$thumbheight || $thumbheight > $this->_imginfo['height']) {
			$thumbheight = $thumbwidth > $this->_imginfo['width'] ? $this->_imginfo['height'] : $this->_imginfo['height'] * ($thumbwidth / $this->_imginfo['width']);
		}

		$copy_photo = imagecreatetruecolor($this->_imginfo['width'], $this->_imginfo['height']);
		imagecopy($copy_photo, $this->_im, 0, 0, 0, 0, $this->_imginfo['width'], $this->_imginfo['height']);
		$attach_photo = $copy_photo;

		$thumb_photo = null;
		switch ($thumbtype) {
			case 'wh':
				$thumb_photo = $this->_resize_bywh($attach_photo, $thumbwidth, $thumbheight);
				break;
			case 'ratio':
				$thumb_photo = $this->_resize_byratio($attach_photo, $thumbwidth, $thumbheight);
				break;
		}

		clearstatcache();

		if ($thumb_photo) {

			$imagefunc = $this->_imagefunc;

			if ($this->_imginfo['mime'] == 'image/jpeg') {
				$thumbquality = 75;
				if ($thumbwidth < 100 && $thumbheight < 100) {
					$thumbquality = 100;
				}
				$imagefunc($thumb_photo, $this->target, $thumbquality);
			} else {
				$imagefunc($thumb_photo, $this->target);
			}

			if (file_exists($this->target)) {
				return true;
			}

		}

		return false;
	}


}


